package com.turnos.domain;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import com.coreweb.domain.Ping;
import com.coreweb.domain.Register;
import com.coreweb.domain.Tipo;
import com.coreweb.util.Misc;
import com.coreweb.util.MyPair;
import com.turnos.Configuracion;

public class RegisterDomain extends Register {

	private static RegisterDomain instance = new RegisterDomain();

	static int pos = 10;
	static RegisterDomain[] list = null;
	static Random r = new Random();

	private RegisterDomain() {
	}

	public synchronized static RegisterDomain NO_getInstance() {
		if (instance == null) {
			list = new RegisterDomain[15];
			for (int i = 0; i < 15; i++) {
				list[i] = new RegisterDomain();
			}
			instance = new RegisterDomain();
		}
		return list[r.nextInt(pos) + 1];
	}

	public synchronized static RegisterDomain getInstance() {
		if (instance == null) {
			instance = new RegisterDomain();
		}
		return instance;
	}

	public List<Cliente> getAllClientes() throws Exception {
		List<Cliente> out = super.getObjects(com.turnos.domain.Cliente.class
				.getName());
		return out;
	}

	public List<Operador> getAllOperarios() throws Exception {
		List<Operador> out = super.getObjects(com.turnos.domain.Operador.class
				.getName());
		return out;
	}

	public List<Servicio> getAllServicios() throws Exception {
		List<Servicio> out = super.getObjects(com.turnos.domain.Servicio.class
				.getName());
		return out;
	}

	public List<Turno> getAllTurnos() throws Exception {
		List<Turno> out = super.getObjects(com.turnos.domain.Turno.class
				.getName());
		return out;
	}

	public List<Puesto> getAllExtras() throws Exception {
		List<Puesto> out = super.getObjects(com.turnos.domain.Puesto.class
				.getName());
		return out;
	}

	public List<Tarea> getAllTareas() throws Exception {
		List<Tarea> out = super.getObjects(com.turnos.domain.Tarea.class
				.getName());
		return out;
	}

	/**
	 * Recibe la clave encriptada y la verifica contra la del usuario pasado
	 * como parametro
	 * 
	 * @param clave
	 * @param usuario
	 * @return true si es valdio el login y false de lo contrario
	 * @throws Exception
	 */
	public boolean validarUsuario(String clave, String usuario)
			throws Exception {
		String query = "select u.clave from Usuario u where u.login='"
				+ usuario + "'";
		List<Object> list = null;
		list = this.hql(query);
		if (list.size() > 0 && clave.compareTo((String) list.get(0)) == 0) {
			return true;
		} else {
			return false;
		}

	}

	public List<Tipo> getTipos(String tipoTipoDescripcion) throws Exception {
		List<Tipo> list = null;
		String query = "select t from Tipo t where t.tipoTipo.descripcion = '"
				+ tipoTipoDescripcion + "'";
		list = this.hql(query);
		return list;
	}

	public AccesoApp getAcceso(String login) throws Exception {
		List<AccesoApp> list = null;
		AccesoApp a = new AccesoApp();
		String queryAcceso = "" + " select ac " + " from AccesoApp ac"
				+ " where ac.usuario.login = ? ";
		list = this.hql(queryAcceso, login);
		if (list.size() == 1) {
			a = list.get(0);
		} else {
			throw new Exception(
					"Error: Este usuario no tiene ningun acceso asignado.");
		}
		return a;
	}

	public Turno getTurnoActual(Long idOperador) throws Exception {
		List<Turno> list = null;
		Turno t = new Turno();
		String queryTurno = "" + " select t " + " from Turno t"
				+ " where t.operador.id = ? and t.estado.sigla like '"
				+ Configuracion.SIGLA_ESTADO_TURNO_ATENDIENDO + "'";
		list = this.hql(queryTurno, idOperador);
		if (list.size() == 1) {
			t = list.get(0);
		} else {
			throw new Exception(
					"Error: Este usuario no tiene ningun turno asignado.");
		}
		return t;
	}

	public List<Turno> getTurnosParaOperador(Long idOperador) throws Exception {
		List<Turno> list = null;
		String queryTurno = ""
				+ " select t "
				+ " from Operador as op, Turno as t join op.servicios as servicio "
				+ " where op.id = ? and t.servicio.id = servicio.id and t.estado.sigla like '"
				+ Configuracion.SIGLA_ESTADO_TURNO_ESPERANDO + "'";
		list = this.hql(queryTurno, idOperador);

		return list;
	}

	public List<Tarea> getTareas(Long idOperador) throws Exception {
		List<Tarea> list = null;
		String queryTarea = "" + " select t " + " from Tarea as t "
				+ " where t.operador.id = ? ";
		list = this.hql(queryTarea, idOperador);

		return list;
	}

	Misc m = new Misc();

	/**
	 * Obtiene las tareas de un operador filtradas por fecha
	 * 
	 * @param idOperador
	 * @return
	 * @throws Exception
	 */
	public List<Tarea> getTareasPorFechas(Long idOperador, Date fechaDesde,
			Date fechaHasta) throws Exception {
		List<Tarea> list = null;
		String queryTarea = "" + " select t " + " from Tarea as t "
				+ " where t.operador.id = ? " + " and t.inicio BETWEEN "
				+ "TO_DATE('" + m.dateToString(fechaDesde, m.YYYY_MM_DD)
				+ "' , '" + m.YYYY_MM_DD + "') AND TO_DATE('"
				+ m.dateToString(fechaHasta, m.YYYY_MM_DD) + "' , '"
				+ m.YYYY_MM_DD + "') " + " order by t.inicio ";

		queryTarea = "" + " select t " + " from Tarea as t "
				+ " where t.operador.id = ? "
				+ " and t.inicio > ?  and t.inicio < ?) "
				+ " order by t.inicio ";

		System.out.println("\n\n" + queryTarea);
		Object[] para = { idOperador, fechaDesde, fechaHasta };

		list = this.hql(queryTarea, para);

		return list;
	}

	/**
	 * Retorna la Razon Social correspondiente al ruc segun la BD del SET
	 */
	public String getRazonSocialSET(String ruc) throws Exception {
		RucSet set = (RucSet) this.getObject(RucSet.class.getName(), "ruc",
				ruc.trim());
		if (set == null) {
			return "";
		}
		return set.getRazonSocial();
	}

	/**
	 * Retorna la Razon Social correspondiente al ruc segun la BD del SET
	 */
	public String getRazonSocialSET_RUC_CI(String ruc) throws Exception {
		String query = "select c.razonSocial from RucSet c where c.ruc"
				+ " like '%" + ruc + "%'";
		List<String> list = this.hql(query);
		if (list.size() == 1) {
			return list.get(0);
		}
		return null;
	}

	/**
	 * Retorna el Cliente recibiendo el ruc
	 */
	public Cliente getClienteByRuc(String ruc) throws Exception {
		String query = "select c from Cliente c where c.ruc" + " like '" + ruc
				+ "'";
		List<Cliente> list = this.hql(query);
		if (list.size() == 1) {
			return list.get(0);
		} else {
			return null;
		}
	}

	/**
	 * Retorna el Cliente recibiendo la cedula
	 */
	public Cliente getClienteByCedula(String cedula) throws Exception {
		String query = "select c from Cliente c where c.cedula" + " like '"
				+ cedula + "'";
		List<Cliente> list = this.hql(query);
		if (list.size() == 1) {
			return list.get(0);
		} else {
			return null;
		}
	}

	/**
	 * Retorna el Cliente Nuevo por Defecto
	 */
	public Cliente getClienteNuevoDefault() throws Exception {
		String cedula = Configuracion.CEDULA_CLIENTE_NUEVO;
		String query = "select c from Cliente c where c.cedula" + " like '"
				+ cedula + "'";
		List<Cliente> list = this.hql(query);
		if (list.size() == 1) {
			return list.get(0);
		} else {
			throw new Exception(
					"Error al buscar el Cliente Nuevo por Defecto..");
		}
	}

	public List<Turno> getTurnosByEstado(String idStr, MyPair estado)
			throws Exception {

		String query = "select t from Turno t " + " where t.numero like '"
				+ idStr + "%' and t.estado.id = " + estado.getId()
				+ " order by t.creacion ";
		List<Turno> list = this.hql(query);
		return list;
	}

	public List<Puesto> getPuestosDisponibles(Long idOperador, Long idServicio)
			throws Exception {
		List<Puesto> list = null;
		String queryPuestos = " select p from Operador o join o.puestos as p where o.id = "
				+ idOperador
				+ " and p in "
				+ " (select ps from Servicio s join s.puestos as ps where s.id = "
				+ idServicio + ") "
		/******
		 * lo comento, porque no se hizo el detalle de varios puestos x zona +
		 * " and p not in " +
		 * " (select t.puesto from Tarea t where t.activa = 'true') "
		 ******************************************************************/
		;
		list = this.hql(queryPuestos);

		return list;
	}

	/**
	 * Buscar si el cliente tiene alguna impresora asignada para imprimir
	 * @param miIp
	 * @return
	 */
	public String getIpImpresora(String miIp) {
		String ipImpresora = null;
		try {
			ipImpresora = (String) this
					.hqlToObject("Select ci.impresora from ClienteImpresora ci where ci.cliente = '"
							+ miIp+"'");
		} catch (Exception e) {
		}
		return ipImpresora;
	}

	public static void main(String[] args) {
		try {

			RegisterDomain rr = RegisterDomain.getInstance();
			List<Puesto> lp = rr.getPuestosDisponibles((long) 8, (long) 8);
			System.out.println("-------------------");
			for (Iterator iterator = lp.iterator(); iterator.hasNext();) {
				Puesto p = (Puesto) iterator.next();
				System.out.println(p.getDescripcion());
			}
			System.out.println("-------------------");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void xxxmain(String[] args) {
		try {
			RegisterDomain rr = RegisterDomain.getInstance();
			Ping p = new Ping();

			rr.saveObject(p, "prueba");
			System.out.println("ok!");

			/*
			 * List<Turno> list = null; String queryTurno = "" + " select t " +
			 * " from Operador as op, Turno as t join op.servicios as servicio "
			 * +
			 * " where op.id = ? and t.servicio.id = servicio.id and t.estado.sigla like '"
			 * + Configuracion.SIGLA_ESTADO_TURNO_ESPERANDO + "'"; list =
			 * rr.hql(queryTurno, 2l);
			 */

			List<Puesto> list = null;
			String queryPuestos = " select p from Operador o join o.puestos as p where o.id = 1 "
					+ " and p in "
					+ " (select ps from Servicio s join s.puestos as ps where s.id = 2) "
					+ " and p not in "
					+ " (select t.puesto from Tarea t where t.activa = 'true') ";
			list = rr.hql(queryPuestos);

			System.out.println("tam: " + list.size());
			for (Puesto puesto : list) {
				System.out.println("Puesto: " + puesto.getDescripcion());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
